﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;

namespace Web7.Utilities
{
    public enum WatermarkPosition
    {
        LeftTop,
        CenterTop,
        RightTop,
        LeftMiddle,
        Center,
        RightMiddle,
        LeftBottom,
        CenterBottom,
        RightBottom
    }

    public class Watermark
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="imageWidth"></param>
        /// <param name="imageHeight"></param>
        /// <param name="watermarImagePath"></param>
        /// <param name="watermarkPosition"></param>
        /// <param name="alpha"></param>
        public static void AddWatermarkImage(Graphics graphics, int imageWidth, int imageHeight, string watermarImagePath, WatermarkPosition watermarkPosition, float alpha)
        {
            if ((graphics != null) && File.Exists(watermarImagePath))
            {
                Image image = new Bitmap(watermarImagePath);
                ImageAttributes imageAttr = new ImageAttributes();
                ColorMap map = new ColorMap
                {
                    OldColor = Color.FromArgb(0xff, 0, 0xff, 0),
                    NewColor = Color.FromArgb(0, 0, 0, 0)
                };
                ColorMap[] mapArray = new ColorMap[] { map };
                imageAttr.SetRemapTable(mapArray, ColorAdjustType.Bitmap);
                float[][] numArray2 = new float[5][];
                float[] numArray3 = new float[5];
                numArray3[0] = 1f;
                numArray2[0] = numArray3;
                numArray3 = new float[5];
                numArray3[1] = 1f;
                numArray2[1] = numArray3;
                numArray3 = new float[5];
                numArray3[2] = 1f;
                numArray2[2] = numArray3;
                numArray3 = new float[5];
                numArray3[3] = alpha;
                numArray2[3] = numArray3;
                numArray3 = new float[5];
                numArray3[4] = 1f;
                numArray2[4] = numArray3;
                float[][] newColorMatrix = numArray2;
                ColorMatrix matrix = new ColorMatrix(newColorMatrix);
                imageAttr.SetColorMatrix(matrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
                int x = 0;
                int y = 0;
                switch (watermarkPosition)
                {
                    case WatermarkPosition.LeftTop:
                        x = 10;
                        y = 10;
                        break;

                    case WatermarkPosition.CenterTop:
                        x = (imageWidth - image.Width) / 2;
                        y = 10;
                        break;

                    case WatermarkPosition.RightTop:
                        x = (imageWidth - image.Width) - 10;
                        y = 10;
                        break;

                    case WatermarkPosition.LeftMiddle:
                        x = 10;
                        y = (imageHeight - image.Height) / 2;
                        break;

                    case WatermarkPosition.Center:
                        x = (imageWidth - image.Width) / 2;
                        y = (imageHeight - image.Height) / 2;
                        break;

                    case WatermarkPosition.RightMiddle:
                        x = (imageWidth - image.Width) - 10;
                        y = (imageHeight - image.Height) / 2;
                        break;

                    case WatermarkPosition.LeftBottom:
                        x = 10;
                        y = (imageHeight - image.Height) - 10;
                        break;

                    case WatermarkPosition.CenterBottom:
                        x = (imageWidth - image.Width) / 2;
                        y = (imageHeight - image.Height) - 10;
                        break;

                    case WatermarkPosition.RightBottom:
                        x = (imageWidth - image.Width) - 10;
                        y = (imageHeight - image.Height) - 10;
                        break;
                }
                graphics.DrawImage(image, new Rectangle(x, y, image.Width, image.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, imageAttr);
                image.Dispose();
                imageAttr.Dispose();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sourceImage"></param>
        /// <param name="watermarImagePath"></param>
        /// <param name="watermarkPosition"></param>
        /// <param name="alpha"></param>
        /// <param name="watermarkQuality"></param>
        /// <param name="newImageStream"></param>
        public static void AddWatermarkImage(Image sourceImage, string watermarImagePath, WatermarkPosition watermarkPosition, float alpha, int watermarkQuality, out Stream newImageStream)
        {
            if ((sourceImage == null) || string.IsNullOrEmpty(watermarImagePath.TrimEnd(new char[] { ' ' })))
            {
                newImageStream = null;
            }
            else
            {
                int width = sourceImage.Width;
                int height = sourceImage.Height;
                Bitmap image = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                image.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
                Graphics graphics = Graphics.FromImage(image);
                graphics.DrawImage(sourceImage, new Rectangle(0, 0, width, height), 0, 0, width, height, GraphicsUnit.Pixel);
                AddWatermarkImage(graphics, width, height, watermarImagePath, watermarkPosition, alpha);
                newImageStream = new MemoryStream();
                ImageCodecInfo encoderInfo = GetEncoderInfo("image/jpeg");
                EncoderParameters encoderParams = new EncoderParameters(1);
                encoderParams = new EncoderParameters();
                encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)watermarkQuality);
                image.Save(newImageStream, encoderInfo, encoderParams);
                image.Dispose();
                sourceImage.Dispose();
                graphics.Dispose();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sourceStream"></param>
        /// <param name="watermarImagePath"></param>
        /// <param name="watermarkPosition"></param>
        /// <param name="alpha"></param>
        /// <param name="watermarkQuality"></param>
        /// <param name="newImageStream"></param>
        public static void AddWatermarkImage(Stream sourceStream, string watermarImagePath, WatermarkPosition watermarkPosition, float alpha, int watermarkQuality, out Stream newImageStream)
        {
            Image sourceImage = null;
            try
            {
                sourceImage = Image.FromStream(sourceStream, true);
            }
            catch
            {
            }
            if (sourceImage == null)
            {
                newImageStream = null;
            }
            else
            {
                AddWatermarkImage(sourceImage, watermarImagePath, watermarkPosition, alpha, watermarkQuality, out newImageStream);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="imageWidth"></param>
        /// <param name="imageHeight"></param>
        /// <param name="watermarText"></param>
        /// <param name="watermarkPosition"></param>
        /// <param name="alpha"></param>
        public static void AddWatermarkText(Graphics graphics, int imageWidth, int imageHeight, string watermarText, WatermarkPosition watermarkPosition, float alpha)
        {
            if ((graphics != null) && !string.IsNullOrEmpty(watermarText.TrimEnd(new char[] { ' ' })))
            {
                graphics.SmoothingMode = SmoothingMode.AntiAlias;
                int[] numArray = new int[] { 0x10, 14, 12, 10, 8, 6, 4, 3, 2, 1 };
                Font font = null;
                SizeF ef = new SizeF();
                for (int i = 0; i < numArray.Length; i++)
                {
                    font = new Font("arial", (float)numArray[i], FontStyle.Bold);
                    ef = graphics.MeasureString(watermarText, font);
                    if (((ushort)ef.Width) < ((ushort)(imageWidth * 0.8)))
                    {
                        break;
                    }
                }
                float height = ef.Height;
                float width = ef.Width;
                float x = 0f;
                float y = 0f;
                switch (watermarkPosition)
                {
                    case WatermarkPosition.LeftTop:
                        x = (imageWidth * 0.01f) + (width / 2f);
                        y = imageHeight * 0.01f;
                        break;

                    case WatermarkPosition.CenterTop:
                        x = ((float)imageWidth) / 2f;
                        y = imageHeight * 0.01f;
                        break;

                    case WatermarkPosition.RightTop:
                        x = (imageWidth * 0.99f) - (width / 2f);
                        y = imageHeight * 0.01f;
                        break;

                    case WatermarkPosition.LeftMiddle:
                        x = (imageWidth * 0.01f) + (width / 2f);
                        y = (((float)imageHeight) / 2f) - (height / 2f);
                        break;

                    case WatermarkPosition.Center:
                        x = ((float)imageWidth) / 2f;
                        y = (((float)imageHeight) / 2f) - (height / 2f);
                        break;

                    case WatermarkPosition.RightMiddle:
                        x = (imageWidth * 0.99f) - (width / 2f);
                        y = (((float)imageHeight) / 2f) - (height / 2f);
                        break;

                    case WatermarkPosition.LeftBottom:
                        x = (imageWidth * 0.01f) + (width / 2f);
                        y = (imageHeight * 0.99f) - height;
                        break;

                    case WatermarkPosition.CenterBottom:
                        x = ((float)imageWidth) / 2f;
                        y = (imageHeight * 0.99f) - height;
                        break;

                    case WatermarkPosition.RightBottom:
                        x = (imageWidth * 0.99f) - (width / 2f);
                        y = (imageHeight * 0.99f) - height;
                        break;
                }
                StringFormat format = new StringFormat
                {
                    Alignment = StringAlignment.Center
                };
                SolidBrush brush = new SolidBrush(Color.FromArgb(Convert.ToInt32((float)(256f * alpha)), 0, 0, 0));
                graphics.DrawString(watermarText, font, brush, x + 1f, y + 1f, format);
                SolidBrush brush2 = new SolidBrush(Color.FromArgb(0x99, 0xff, 0xff, 0xff));
                graphics.DrawString(watermarText, font, brush2, x, y, format);
                brush.Dispose();
                brush2.Dispose();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sourceImage"></param>
        /// <param name="watermarText"></param>
        /// <param name="watermarkPosition"></param>
        /// <param name="alpha"></param>
        /// <param name="watermarkQuality"></param>
        /// <param name="newImageStream"></param>
        public static void AddWatermarkText(Image sourceImage, string watermarText, WatermarkPosition watermarkPosition, float alpha, int watermarkQuality, out Stream newImageStream)
        {
            if ((sourceImage == null) || string.IsNullOrEmpty(watermarText.TrimEnd(new char[] { ' ' })))
            {
                newImageStream = null;
            }
            else
            {
                int width = sourceImage.Width;
                int height = sourceImage.Height;
                Bitmap image = new Bitmap(width, height, PixelFormat.Format24bppRgb);
                image.SetResolution(sourceImage.HorizontalResolution, sourceImage.VerticalResolution);
                Graphics graphics = Graphics.FromImage(image);
                graphics.DrawImage(sourceImage, new Rectangle(0, 0, width, height), 0, 0, width, height, GraphicsUnit.Pixel);
                AddWatermarkText(graphics, width, height, watermarText, watermarkPosition, alpha);
                newImageStream = new MemoryStream();
                ImageCodecInfo encoderInfo = GetEncoderInfo("image/jpeg");
                EncoderParameters encoderParams = new EncoderParameters(1);
                encoderParams = new EncoderParameters();
                encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, (long)watermarkQuality);
                image.Save(newImageStream, encoderInfo, encoderParams);
                image.Dispose();
                sourceImage.Dispose();
                graphics.Dispose();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sourceStream"></param>
        /// <param name="watermarText"></param>
        /// <param name="watermarkPosition"></param>
        /// <param name="alpha"></param>
        /// <param name="watermarkQuality"></param>
        /// <param name="newImageStream"></param>
        public static void AddWatermarkText(Stream sourceStream, string watermarText, WatermarkPosition watermarkPosition, float alpha, int watermarkQuality, out Stream newImageStream)
        {
            Image sourceImage = null;
            try
            {
                sourceImage = Image.FromStream(sourceStream, true);
            }
            catch
            {
            }
            if (sourceImage == null)
            {
                newImageStream = null;
            }
            else
            {
                AddWatermarkText(sourceImage, watermarText, watermarkPosition, alpha, watermarkQuality, out newImageStream);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="mimeType"></param>
        /// <returns></returns>
        public static ImageCodecInfo GetEncoderInfo(string mimeType)
        {
            ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders();
            foreach (ImageCodecInfo info in imageEncoders)
            {
                if (info.MimeType == mimeType)
                {
                    return info;
                }
            }
            return null;
        }

    }
}
